﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Text;

namespace TfL
{
    public interface IStationNameFeed : ITrackerNetFeedPoller<StationName>, System.Reactive.Subjects.ISubject<StationName>, IDisposable
    {
    }

    public class StationNameFeed : IStationNameFeed
    {

        public StationNameFeed(string url, string ns)
        {
            
            foreach(string line in LineCodes.Names)
            {
                _lineStationTrainTimes.Add(new TrainTimesFeed(url,ns,line));
            }
        }

        #region IObserver<StationName> Members

        public void OnCompleted()
        {
            _subject.OnCompleted();
        }

        public void OnError(Exception error)
        {
            _subject.OnError(error);
        }

        public void OnNext(StationName value)
        {
            if (!_names.Contains(value.Name))
            {
                _names.Add(value.Name);
                _subject.OnNext(value);
            }
        }

        #endregion

        #region IObservable<StationName> Members

        public IDisposable Subscribe(IObserver<StationName> observer)
        {
            return _subject.Subscribe(observer);
        }

        #endregion

        private readonly Subject<StationName> _subject = new Subject<StationName>();

        #region ITrackerNetFeedPoller<StationName> Members

        public ISubject<StationName> Poll()
        {
            _names.Clear();
            foreach(var observable in _lineStationTrainTimes)
            {
                var subscriber = from t in observable.Poll()
                                 select new StationName{Code = t.Code,Name=t.Name,Line =t.Line};
                _subscribers.Add(subscriber.Subscribe(OnNext));
            }
            return this;
        }

        public ISubject<StationName> Poll(System.Threading.CancellationToken token, int period)
        {
            _names.Clear();
            foreach (var subscriber in _lineStationTrainTimes.Select(observable => (from t in observable.Poll(token,period)
                                                                                    select new StationName { Code = t.Code, Name = t.Name, Line = t.Line })))
            {
                _subscribers.Add(subscriber.Subscribe(OnNext));
            }
            return this;
        }

        #endregion

        #region IDisposable Members

        public void Dispose()
        {
            foreach (var subscriber in _subscribers)
            {
                subscriber.Dispose();
            }
        }

        #endregion

        
        private readonly List<IDisposable> _subscribers = new List<IDisposable>(); 

        private readonly List<TrainTimesFeed> _lineStationTrainTimes = new List<TrainTimesFeed>();

        private List<string> _names = new List<string>();
    }
}
